音频组件 API
微信小程序从基础库 1.6 开始不再维护 audio 组件,推荐使用 uni.createInnerAudioContext() API 进行音频播放控制。本节详细讲解该 API 的完整使用方法,包括播放控制、时间获取、状态管理和边界情况处理。
createInnerAudioContext API
创建音频上下文
// 注意:不能使用 ref 包裹,否则后续无法正常 play/stop
const innerAudioContext = uni.createInnerAudioContext()
// 在 onMounted 中设置音频源
onMounted(() => {
innerAudioContext.src = 'https://example.com/audio.mp3'
})
javascript
关键注意:innerAudioContext 必须定义在 setup 的外层或使用 shallowRef,不能使用 ref 包裹。使用 ref 后,重新赋值 src 时会导致 play() 和 stop() 方法失效。
TypeScript 类型支持
如果 HBuilderX 提示找不到 uni 的类型定义,在项目根目录创建 types.d.ts:
/// <reference types="@dcloudio/types" />
declare namespace UniApp {
interface CreateInnerAudioContextOptions {
src?: string
}
}
typescript
核心方法与事件
播放控制
// 播放
innerAudioContext.play()
// 暂停
innerAudioContext.pause()
// 停止
innerAudioContext.stop()
// 跳转到指定位置(秒)
innerAudioContext.seek(170)
javascript
事件监听
| 事件 | 说明 | 触发时机 |
|---|---|---|
onCanplay | 可以播放 | 音频加载完成,可以开始播放 |
onPlay | 开始播放 | 调用 play() 后 |
onPause | 暂停 | 调用 pause() 后 |
onStop | 停止 | 调用 stop() 后 |
onEnded | 自然结束 | 音频播放到末尾 |
onTimeUpdate | 播放进度更新 | 播放过程中持续触发 |
onError | 错误 | 音频加载或播放出错 |
完整音频播放器实现
<template>
<view class="p-4">
<view class="flex items-center justify-between">
<!-- 播放/暂停按钮 -->
<view class="flex items-center" @click="togglePlay">
<up-icon
:name="isPlay ? 'pause-circle' : 'play-fill'"
size="28"
/>
<text class="pl-2 font-bold">音频标题</text>
</view>
<!-- 时间显示 -->
<view class="flex">
<text>{{ current }}</text>
<text>/</text>
<text>{{ total }}</text>
</view>
</view>
<!-- 测试按钮:跳转到末尾 -->
<up-button @click="testEnd">跳转到结尾测试</up-button>
</view>
</template>
<script setup>
import { ref, onMounted } from 'vue'
const isPlay = ref(false)
const current = ref('00:00')
const total = ref('00:00')
const innerAudioContext = uni.createInnerAudioContext()
// 格式化时间(秒 → mm:ss)
function formatTime(seconds) {
const mins = Math.floor(seconds / 60)
const secs = Math.floor(seconds % 60)
return `${String(mins).padStart(2, '0')}:${String(secs).padStart(2, '0')}`
}
onMounted(() => {
innerAudioContext.src = 'https://example.com/test-audio.mp3'
// 音频加载完成
innerAudioContext.onCanplay(() => {
console.log('audio can play')
total.value = formatTime(innerAudioContext.duration)
current.value = formatTime(0)
})
// 播放状态
innerAudioContext.onPlay(() => {
isPlay.value = true
})
innerAudioContext.onPause(() => {
isPlay.value = false
})
// 播放进度
innerAudioContext.onTimeUpdate(() => {
current.value = formatTime(innerAudioContext.currentTime)
})
// 播放结束
innerAudioContext.onEnded(() => {
isPlay.value = false
current.value = formatTime(0)
})
})
// 播放/暂停切换
function togglePlay() {
if (!innerAudioContext) return
if (isPlay.value) {
innerAudioContext.pause()
} else {
innerAudioContext.play()
}
}
// 测试:跳转到接近结尾的位置
function testEnd() {
innerAudioContext.seek(170) // 跳转到 170 秒
}
</script>
vue
边界情况处理
播放结束后的状态恢复
音频播放到末尾后,需要:
- 将
isPlay重置为false - 将
currentTime重置为'00:00'
通过 onEnded 事件处理:
innerAudioContext.onEnded(() => {
isPlay.value = false
current.value = formatTime(0)
})
javascript
重新播放
播放结束后再次点击播放按钮,应该能正常从头开始播放。onEnded 之后调用 play() 会自动从头播放。
时间格式化
duration 和 currentTime 返回的是秒数(浮点数),需要格式化为 mm:ss 格式显示。初始化时 currentTime 可能为 0,需要在 onCanplay 中设置初始值。
背景音频 API
uni-app 还提供了 uni.getBackgroundAudioManager() 用于后台音频播放,适用于音乐类小程序。大多数知识付费场景使用 createInnerAudioContext 即可。
封装为组件
音频播放器可以封装为基础组件:
<!-- components/audio-player/audio-player.vue -->
<script setup>
defineProps({
src: { type: String, required: true },
title: { type: String, default: '' }
})
// 封装上述播放逻辑
</script>
vue
使用时传入音频 URL 即可:
<audio-player src="https://xxx/audio.mp3" title="第一课:课程介绍" />
vue
↑